﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Data;
using System.Data.SqlClient;
using System.Collections;
using System.IO;
using System.Windows.Forms;

namespace BK_SERVER
{
   
    
    // Lớp giữ đối số cho sự kiện StatusChanged
    
    public class StatusChangedEventArgs : EventArgs
    {
        // Dữ liệu mô tả cho sự kiện
        private string EventMsg;
       
        // Sự kiện nhận và gửi thông điệp
        public string EventMessage
        {
            get
            {
                return EventMsg;
            }
            set
            {
                EventMsg = value;
            }
        }

      
        // Khởi tạo lớp
        public StatusChangedEventArgs(string strEventMsg)
        {
            EventMsg = strEventMsg;
        }
    }


    // Xác định đối tượng Handler đang tham chiếu 
    public delegate void StatusChangedEventHandler(object sender, StatusChangedEventArgs e);
   
    
    
    // Lớp xử lí các sự kiện trên server
    class ServerProcess
    {
        // IP server
        private IPAddress ipAddr;
        // Port server
        private int portNumber;
        // Giữ kết nối từ client
        //public static TcpClient tcpClient;
        private TcpClient tcpClient;
        // Lắng nghe các kết nối
        //public static TcpListener tcpServer;
        private static TcpListener tcpServer;
        // Bảng giữ các user và các kết nối tương ứng
        public static Hashtable htUsers = new Hashtable(50);
        public static Hashtable htConnections = new Hashtable(50);
        // Thread dùng để lắng nghe các thông điệp
        private  static Thread threadListener;
        // Handler xử lí truyền dữ liệu qua các lớp
        public static event StatusChangedEventHandler StatusChanged;
        // Đối tượng truyền tin
        private static StatusChangedEventArgs StatusEvent;
        // chuoi ket noi csdl
        public static string MyConnectionString;
        public static void ExitServer()
        {
            if (threadListener != null)
                threadListener.Abort();
            if (tcpServer != null)
            {
                tcpServer.Stop();
            }
        }
        public void killThread()
        {
            if(tcpClient != null)
                tcpClient.Close();
        }
        // Khởi tạo server, lấy IP và Port
        public ServerProcess(IPAddress ip, string port)
        {
            ipAddr = ip;
            portNumber = (int)Int32.Parse(port);
            MyConnectionString = System.Environment.CurrentDirectory;
            MyConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFilename=\'" + MyConnectionString + "\\" + "chat_database.mdf\';Integrated Security=True;User Instance=True";
        }
      
        
        // Bắt đầu lắng nghe, tạo ra một đối tượng tcpServer để lắng nghe, tạo thread để chờ các kết nối
        // Thành công --> server được khởi tạo
        // Thất bại --> Thông báo lỗi
       
        public void StartListenning()
        {
            try
            {
                tcpServer = new TcpListener(ipAddr,portNumber);
                tcpServer.Start();
                threadListener = new Thread(KeepListenning);
                threadListener.Start();
            }
            catch
            {
                MessageBox.Show("Không thể khởi tạo server");
            }
        }
        
      
        // Phương thức sử dụng để giữ kết nối
        // Luôn lắng nghe, nếu có đối tượng kết nối tới thì tạo ra một đối tượng ProcessClient
        // để xử lí
       
        private void KeepListenning()
        {
            while (true)
            {
                 tcpClient = tcpServer.AcceptTcpClient();
                 if (tcpClient != null)
                 {
                    ProcessClient newConn = new ProcessClient(tcpClient);
                 }

            }
        }
        // gọi phương thức khi muốn cập nhật the StatusChanged event
        
        public static void OnStatusChanged(StatusChangedEventArgs e)
        {
            StatusChangedEventHandler statusHandler = StatusChanged;
            if (statusHandler != null)
            {
                // Invoke the delegate
                statusHandler(null, e);
            }
        }

      
        //  Gửi tin nhắn tới form server
        public static void ShowMessageLog(string svResponse)
        {
            StatusEvent = new StatusChangedEventArgs(svResponse);
            OnStatusChanged(StatusEvent);
        }
        // Thêm thành viên vào các mảng lưu trữ trên server
        public static void AddUser(TcpClient tcpUser, string userName)
        {
            // Thêm tên người dùng và kết nối tương ứng vào cả hai bảng dữ liệu
            ServerProcess.htUsers.Add(userName, tcpUser);
            ServerProcess.htConnections.Add(tcpUser, userName);
        }

        // Xóa người dùng trong hai mảng dữ liệu
        public static void RemoveUser(TcpClient tcpUser)
        {
            // Nếu người dùng tồn tại
            if (htConnections[tcpUser] != null)
            {
                // Thông báo tới server kết nối bị ngắt
                ShowMessageLog(htConnections[tcpUser] + " is disconnected");

                // Xóa thành viên khỏi các bảng lưu trữ
                ServerProcess.htUsers.Remove(ServerProcess.htConnections[tcpUser]);
                ServerProcess.htConnections.Remove(tcpUser);
            }
        }

     
        // Update danh sách các thành viên
        
        public static void UpdateMembersList(TcpClient newClient, string newMem)
        {
            StreamWriter swSenderList;
            // Tạo một mảng các TcpClients, kích thước bằng số người dùng hiện có
            TcpClient[] tcpClients = new TcpClient[ServerProcess.htUsers.Count];
            // Coppy các đối tượng này vào các phần tử của mảng
            ServerProcess.htUsers.Values.CopyTo(tcpClients, 0);
            string path = MyConnectionString;
            SqlConnection ketnoi = new SqlConnection();
            ketnoi.ConnectionString = path;
            SqlCommand lenhsql = new SqlCommand();
           
            // Lặp hết danh sách
            for (int i = 0; i < tcpClients.Length; i++)
            {
                // Gửi tin nhắn tới mỗi thành viên
                try
                {
                    // Nếu tin nhắn trống hoặc kết nối đầy --> ko thực hiện
                    if (newMem.Trim() == null || tcpClients[i] == null)
                    {
                        continue;
                    }
                    // Lấy danh sách bạn bè
                    string friends = ProcessClient.list_friend;
                  
                    if(friends != null )
                    {
                        // Gửi tên thành viên mới đăng nhập tới các thành viên khác 
                        while (friends.Length > 0)
                        {
                            int vt = friends.IndexOf("#");
                            string name = friends.Substring(0, vt);
                            friends = friends.Remove(0, vt + 1);
                            if (newMem.Equals(name) == false)
                            {
                                if (tcpClients[i].Equals(htUsers[name]) == true)
                                {
                                    lenhsql.CommandText = "Select GROUP_NAME from ACCOUNT A, [GROUP] G, FRIEND F where  F.FRIEND_NAME='" + newMem + "' AND F.ID_GROUP = G.ID_GROUP AND G.ID_USER = A.ID_USER AND A.USER_NAME = '" + name + "'";
                                    lenhsql.CommandType = CommandType.Text;
                                    lenhsql.Connection = ketnoi;
                                    ketnoi.Open();
                                    SqlDataReader readIdFriend = lenhsql.ExecuteReader();
                                    string aGroup = "";
                                    while (readIdFriend.Read())
                                        aGroup = (string)readIdFriend["GROUP_NAME"];
                                    ketnoi.Close();
                                    if (aGroup == "")
                                    {
                                        aGroup = "No Group";
                                    }
                                    string sendMsg = aGroup + "&&" + newMem + "$#";
                                    swSenderList = new StreamWriter(tcpClients[i].GetStream());
                                    swSenderList.WriteLine("#NEW_USER#" + sendMsg);
                                    swSenderList.Flush();
                                    swSenderList = null;
                                }
                            }
                        }
                        
                    }
                }
                catch // Kết nối nào bị lỗi thì xóa đi
                {
                    //RemoveUser(tcpClients[i]);
                }
                // Cho thread ngủ để đảm bảo dữ liệu đã gửi thành công
                Thread.Sleep(100);
            }
            // Gửi danh sách các thành viên(bạn bè) của user mới đăng nhập tới user đó
            swSenderList = new StreamWriter(newClient.GetStream());
            string list_friend = "#NEW_USER#" + ProcessClient.list;
            swSenderList.WriteLine(list_friend);
            swSenderList.Flush();
            swSenderList = null;
            ProcessClient.list_friend = "";
            ProcessClient.list = "";
        }

        // Gửi thông điệp giữa các thành viên
       
        public static void SendMessage(string friend, string msg)
        {
            StreamWriter swSenderList;
            // Tạo một mảng các TcpClients, kích thước bằng số người dùng hiện có
            TcpClient[] tcpClients = new TcpClient[ServerProcess.htUsers.Count];
            // Coppy các đối tượng này vào các phần tử của mảng
            ServerProcess.htUsers.Values.CopyTo(tcpClients, 0);
           
            
            // Lặp hết danh sách
            for (int i = 0; i < tcpClients.Length; i++)
            {
                // Nếu tin nhắn trống hoặc kết nối đầy --> ko thực hiện
                if (msg.Trim() == "" || tcpClients[i] == null)
                {
                    continue;
                }
                if (tcpClients[i].Equals(htUsers[friend]) == true)
                {
                    try
                    {
                        swSenderList = new StreamWriter(tcpClients[i].GetStream());
                        swSenderList.WriteLine(msg);
                        swSenderList.Flush();
                        swSenderList = null;
                    }
                    catch
                    {
                        //MessageBox.Show("Không thể chuyển dữ liệu");
                    }
                }
               
                // Cho thread ngủ để đảm bảo dữ liệu đã gửi thành công
                Thread.Sleep(100);
            }
        }
    }

    // Lớp xử lí khi có kết nối mới
    class ProcessClient
    {
        // Đối tượng kết nối của thành viên
        TcpClient tcpClient;
        // Thread để chuyên nhận tin nhắn
        public  Thread aThreadClient;
        // Đối tượng nhận dòng dữ liệu
        private  StreamReader receiver;
        // chuỗi lưu trữ tin nhắn nhận được
        private string msg_Exchanged;
        // Danh sách thành viên gồm cả nhóm tương ứng 
        public static string list = "";
        // Danh sách thành viên ko có tên nhóm
        public static string list_friend = "";
        // Trạng thái thông tin sau khi được xử lí
        private string noticeStatus;
        public static string MyConnectionString;    
       
        // Khởi tạo, gán đối tượng lắng nghe kết nối
        // Tạo thread xử lí thông điệp
       
        public ProcessClient(TcpClient newClient)
        {
            tcpClient = newClient;
            aThreadClient = new Thread(new ThreadStart(Processing));
            aThreadClient.Start();

            MyConnectionString = System.Environment.CurrentDirectory;
            MyConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFilename=\'" + MyConnectionString + "\\" + "chat_database.mdf\';Integrated Security=True;User Instance=True";
        }

        // Kết thúc chương trình, cập nhật lại trạng thái(offline), giải phóng tài nguyên
      
        public static void Exit()
        {
            try
            {
                string path = MyConnectionString;
                SqlConnection ketnoi = new SqlConnection();
                ketnoi.ConnectionString = path;
                SqlCommand lenhsql = new SqlCommand();
                lenhsql.CommandText = "Update ACCOUNT SET STATUS = '0'";
                lenhsql.CommandType = CommandType.Text;
                lenhsql.Connection = ketnoi;
                ketnoi.Open();
                lenhsql.ExecuteNonQuery();
                ketnoi.Close();
            }
            catch { }
        }
       
        
        // Phương thức xử lí thông điệp
        // Đầu tiên nhận một tin nhắn đăng kí hoặc đăng nhập
        // gọi tới phương thức Process_Msg để xử lí
        // Thành công --> tiếp tục lắng nghe các thông điệp và có xử lí tương ứng
        // Thất bại --> kết thức 
       
        public void Processing()
        {
           
            // Nhận thông điệp đầu tiên
          
            receiver = new StreamReader(tcpClient.GetStream());
            msg_Exchanged = receiver.ReadLine();
            if (ProcessMsg(msg_Exchanged) == true)
            {
               
                // Thông điệp đầu hợp lệ
               
                try
                {
                    receiver = new StreamReader(tcpClient.GetStream());
                    // Nhận dữ liệu
                    while ((msg_Exchanged = receiver.ReadLine()) != "")
                    {                        
                        if(msg_Exchanged != null)
                        {
                            ServerProcess.ShowMessageLog(msg_Exchanged);
                            string msg = msg_Exchanged;
                            string tempMsg;
                            // Lấy mã thông điệp
                            string head = msg.Substring(0, 10);
                            // Lấy nội dung thông điệp
                            msg = msg.Remove(0, 10);
                            // Xử lí với các mã thông điệp tương ứng
                            switch (head)
                            {
                               
                                
                                // Các thành viên gửi thông điệp cho nhau
                                // Lấy tên người gửi và người nhận --> gửi thông điệp
                               
                                case "#SEND_MSG#":
                                    string destination;
                                    tempMsg = "#SEND_MSG#";
                                    destination = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    tempMsg += msg;
                                    ServerProcess.SendMessage(destination, tempMsg);
                                    break;
                               
                                
                                // Các thành viên gửi file cho nhau
                                // Lấy tên người gửi và người nhận --> gửi thông điệp
                               
                                case "#SENDFILE#":
                                    tempMsg = "#SENDFILE#";
                                    destination = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0,( msg.IndexOf("#") + 1) );
                                    tempMsg += msg;
                                    ServerProcess.SendMessage(destination, tempMsg);
                                    break;
                                // Các thành viên yêu cầu xem webcam của bạn chat

                                case "#RQWEBCAM#":
                                    tempMsg = "#RQWEBCAM#";
                                    destination = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    tempMsg += msg;
                                    string remoteEP = tcpClient.Client.RemoteEndPoint.ToString();
                                    tempMsg += remoteEP.Substring(0, remoteEP.IndexOf(":"));
                                    ServerProcess.SendMessage(destination, tempMsg);
                                    break;

                                case "#RPWEBCAM#":
                                    tempMsg = "#RPWEBCAM#";
                                    destination = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    tempMsg += msg;
                                    ServerProcess.SendMessage(destination, tempMsg);
                                    break;
                                
                                // Các thành viên lập phòng chat
                                // Lấy tên người gửi, lọc danh sách thành viên và gửi tới từng người
                               
                                case "#CHATROOM#":
                                    tempMsg = "#CHATROOM#";
                                    destination = msg.Substring(0, msg.IndexOf("#"));
                                    destination += "$";
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    string room = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    string send = msg.Substring(0,msg.IndexOf("#"));
                                    tempMsg += room + "#"  + msg;
                                    while(destination.Length > 1)
                                    {
                                        int vt = destination.IndexOf("$");
                                        string client = destination.Substring(0,vt);
                                        destination = destination.Remove(0, vt + 1);
                                        if(client.Equals(send) == false)
                                        {
                                            ServerProcess.SendMessage(client, tempMsg);
                                        }
                                    }
                                    break;
                                // Cập nhật thành viên mới của phòng chat tới các thành viên cũ
                                case "#USERROOM#":
                                    tempMsg = "#USERROOM#";
                                    string sendPerson = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    destination = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    string roomC = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    string newMember = msg;
                                    tempMsg += roomC + "#" + msg;

                                    string pathKn = MyConnectionString;
                                    SqlConnection ketnoiKn = new SqlConnection();
                                    ketnoiKn.ConnectionString = pathKn;
                                    SqlCommand lenhsqlKn = new SqlCommand();
                                    lenhsqlKn.CommandText = "Select ID_USER from ACCOUNT Where USER_NAME='" + newMember + "' AND STATUS = '1'";
                                    lenhsqlKn.CommandType = CommandType.Text;
                                    lenhsqlKn.Connection = ketnoiKn;
                                    ketnoiKn.Open();
                                    int statusKn = 0;
                                    SqlDataReader kn = lenhsqlKn.ExecuteReader();
                                    while (kn.Read())
                                        statusKn = (int)kn["ID_USER"];
                                    ketnoiKn.Close();
                                    if (statusKn != 0)
                                    {   
                                        while (destination.Length > 1)
                                        {
                                            int vt = destination.IndexOf("$");
                                            string client = destination.Substring(0, vt);
                                            destination = destination.Remove(0, vt + 1);
                                            if ((client != "") && (client.Equals(newMember) == false))
                                            {
                                                ServerProcess.SendMessage(client, tempMsg);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        tempMsg = "#FRNOT_ON#" + destination + "#" + roomC;
                                        ServerProcess.SendMessage(sendPerson, tempMsg);
                                    }
                                    break;
                                // Gửi danh sách các thành viên của phòng tới thành viên mới
                                case "#LISTROOM#":
                                    tempMsg = "#LISTROOM#";
                                    string sendPersonList = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    destination = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    string roomList = msg.Substring(0, msg.IndexOf("#"));
                                    string pathKn1 = MyConnectionString;
                                    SqlConnection ketnoiKn1 = new SqlConnection();
                                    ketnoiKn1.ConnectionString = pathKn1;
                                    SqlCommand lenhsqlKn1 = new SqlCommand();
                                    lenhsqlKn1.CommandText = "Select ID_USER from ACCOUNT Where USER_NAME='" + destination + "' AND STATUS = '1'";
                                    lenhsqlKn1.CommandType = CommandType.Text;
                                    lenhsqlKn1.Connection = ketnoiKn1;
                                    ketnoiKn1.Open();
                                    int statusKn1 = 0;
                                    SqlDataReader kn1 = lenhsqlKn1.ExecuteReader();
                                    while(kn1.Read())
                                        statusKn1 = (int)kn1["ID_USER"];
                                    ketnoiKn1.Close();
                                    if (statusKn1 != 0)
                                    {
                                        tempMsg += sendPersonList + "$$" + msg;   
                                        if(destination != "")
                                            ServerProcess.SendMessage(destination, tempMsg);
                                    }
                                    else
                                    {
                                        tempMsg = "#FRNOT_ON#" + destination + "#" +roomList ;
                                        ServerProcess.SendMessage(sendPersonList, tempMsg);
                                    }
                                    break;
                                // Gửi file trong chat room
                                case "#SENDROOM#":
                                    tempMsg = "#SENDROOM#";
                                    destination = msg.Substring(0, msg.IndexOf("#"));
                                    destination += "$";
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    string roomN = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    string sendN = msg.Substring(0, msg.IndexOf("#"));
                                    tempMsg += roomN + "#" + msg;
                                    while (destination.Length > 0)
                                    {
                                        int vt = destination.IndexOf("$");
                                        string client = destination.Substring(0, vt);
                                        destination = destination.Remove(0, vt + 1);
                                        if ((client != "") && (client.Equals(sendN) == false))
                                            ServerProcess.SendMessage(client, tempMsg);
                                    }
                                    break;
                                case "#OUT_ROOM#":
                                    tempMsg = "#OUT_ROOM#";
                                    destination = msg.Substring(0, msg.IndexOf("#"));
                                    destination += "$";
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    string roomName = msg.Substring(0, msg.IndexOf("#"));
                                    string roomMember = msg.Remove(0, msg.IndexOf("#") + 1);
                                    tempMsg = tempMsg + roomMember + "#" + roomName;
                                    while (destination.Length > 0)
                                    {
                                        int vt = destination.IndexOf("$");
                                        string client = destination.Substring(0, vt);
                                        destination = destination.Remove(0, vt + 1);
                                        if ((client != "") && (client.Equals(roomMember) == false))
                                            ServerProcess.SendMessage(client, tempMsg);
                                    }
                                    break;
                                // Thành viên thay đổi avatar
                                case "#AVATARUD#":
                                    tempMsg = "#AVATARUD#";
                                    destination = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    tempMsg += msg;
                                    while (destination.Length > 0)
                                    {
                                        int vt = destination.IndexOf("$");
                                        string client = destination.Substring(0, vt);
                                        destination = destination.Remove(0, vt + 1);
                                        if (client != "")
                                            ServerProcess.SendMessage(client, tempMsg);
                                    }
                                    break;
                                // Thành viên đăng xuất
                                // Gửi thông tin này tới các bạn bè của thành viên đăng xuất
                                // Cập nhật lại trạng thái của thành viên
                                case "#NOT_JOIN#":
                                    tempMsg = "#NOT_JOIN#";
                                    destination = msg.Substring(0, msg.IndexOf("#"));
                                    msg = msg.Remove(0, (msg.IndexOf("#") + 1));
                                    tempMsg += msg;
                                    ServerProcess.SendMessage(destination, tempMsg);
                                    break;
                                case "#USLOGOUT#":
                                    // connect to database
                                    string path = MyConnectionString;
                                    SqlConnection ketnoi = new SqlConnection();
                                    ketnoi.ConnectionString = path;
                                    SqlCommand lenhsql = new SqlCommand();
                                    // Lay userName
                                    int pos = msg.IndexOf("#");
                                    string userName = msg.Substring(0, pos);
                                    msg = msg.Remove(0, pos + 1);
                                    // Lay pass
                                    pos = msg.IndexOf("#$#");
                                    string pass = msg.Substring(0, pos);
                                    msg = msg.Remove(0, pos + 1);
                                    lenhsql.CommandText = "Select * from ACCOUNT Where USER_NAME='" + userName + "' AND PASSWORD = '" + pass + "'";
                                    lenhsql.CommandType = CommandType.Text;
                                    lenhsql.Connection = ketnoi;
                                    ketnoi.Open();
                                    int status = (int)lenhsql.ExecuteScalar();
                                    ketnoi.Close();
                                    if (status != 0)
                                    {
                                        lenhsql.CommandText = "Select * from ACCOUNT AC,[GROUP] G, FRIEND F Where AC.USER_NAME='" + userName + "' AND AC.ID_USER = G.ID_USER  AND G.ID_GROUP = F.ID_GROUP";
                                        lenhsql.CommandType = CommandType.Text;
                                        lenhsql.Connection = ketnoi;
                                        ketnoi.Open();
                                        // get list friend and tell them you log out
                                        tempMsg = "#USLOGOUT#" + userName + "#";
                                        SqlDataReader reader = lenhsql.ExecuteReader();
                                        while (reader.Read())
                                        {
                                            string friends =(string)reader["FRIEND_NAME"];
                                            ServerProcess.SendMessage(friends,tempMsg);
                                        }
                                        ketnoi.Close();
                                        lenhsql.CommandText = "Update ACCOUNT SET STATUS = '0' where USER_NAME = '" + userName + "'";
                                        lenhsql.CommandType = CommandType.Text;
                                        lenhsql.Connection = ketnoi;
                                        ketnoi.Open();
                                        lenhsql.ExecuteNonQuery();
                                        ketnoi.Close();
                                        ServerProcess.ShowMessageLog(userName + " is logged out");
                                        ServerProcess.RemoveUser(tcpClient);
                                        aThreadClient.Abort();
                                    }
                                    break;
                               
                                
                                // Thêm bạn
                                // Kiểm tra xem tài khoản có tồn tại không
                                // Nếu không tồn tại --> gửi thông báo trở lại thành viên gửi yêu cầu
                                // Nếu tồn tại:
                                // + Thành viên đã ở trong nhóm --> gửi thông tin này tới thành viên gửi yêu cầu
                                // + Nhóm đã tồn tại --> Thêm thành viên vào nhóm tương ứng
                                // + NHóm chưa tồn tại --> Tạo nhóm mới và thêm thành viên vào
                                // ==> Gửi thông báo phản hồi tới thành viên gửi yêu cầu 
                              
                                case "#ADDFREND#":
                                    // connect to database
                                    string path2 = MyConnectionString;
                                    SqlConnection ketnoi2 = new SqlConnection();
                                    ketnoi2.ConnectionString = path2;
                                    SqlCommand lenhsql2 = new SqlCommand();
                                    pos = msg.IndexOf("#");
                                    string friendName = msg.Substring(0, pos);
                                    msg = msg.Remove(0, pos + 1);
                                    pos = msg.IndexOf("#");
                                    string sendName = msg.Substring(0, pos);
                                    msg = msg.Remove(0, pos + 1);
                                    string groupName = msg;
                                    lenhsql2.CommandText = "Select ID_USER from  ACCOUNT Where USER_NAME = '" + friendName + "'";
                                    lenhsql2.CommandType = CommandType.Text;
                                    lenhsql2.Connection = ketnoi2;
                                    ketnoi2.Open();
                                    SqlDataReader readId = lenhsql2.ExecuteReader();
                                    int fId = 0;
                                    while(readId.Read())
                                      fId= (int)readId["ID_USER"];
                                    ketnoi2.Close();
                                    if (fId > 0)
                                    {
                                        lenhsql2.CommandText = "Select G.ID_GROUP, G.ID_USER, G.GROUP_NAME from  [GROUP] G, ACCOUNT A  where  A.USER_NAME = '" + sendName + "' AND A.ID_USER = G.ID_USER";
                                        lenhsql2.CommandType = CommandType.Text;
                                        lenhsql2.Connection = ketnoi2;
                                        ketnoi2.Open();
                                        int gId =0;
                                        int uId =0;
                                        SqlDataReader read = lenhsql2.ExecuteReader();
                                        while(read.Read())
                                        {
                                            if (groupName.Equals((string)read["GROUP_NAME"])== true)
                                            { 
                                                gId= (int)read["ID_GROUP"];
                                                uId= (int)read["ID_USER"];
                                            }
                                        }
                                        ketnoi2.Close();
                                        if(gId > 0)
                                        {
                                            lenhsql2.CommandText = "Select ID_FRIEND from FRIEND where ID_GROUP = '" + gId + "' AND ID_FRIEND ='"+fId+"'";
                                            lenhsql2.CommandType = CommandType.Text;
                                            lenhsql2.Connection = ketnoi2;
                                            ketnoi2.Open();
                                            SqlDataReader readIdFriend = lenhsql2.ExecuteReader();
                                            int friendId = 0;
                                            while(readIdFriend.Read())
                                                 friendId= (int)readIdFriend["ID_FRIEND"];
                                            ketnoi2.Close();
                                            if (friendId != 0)
                                            {
                                                ServerProcess.SendMessage(sendName, "#ADD_FAIL#Tài khoản:" + friendName + " đã tồn tại trong nhóm " + groupName);
                                            }
                                            else
                                            { 
                                                lenhsql2.CommandText = "Insert into FRIEND(ID_FRIEND,ID_GROUP,FRIEND_NAME) values('" + fId + "','" + gId + "','" + friendName + "')";
                                                lenhsql2.CommandType = CommandType.Text;
                                                lenhsql2.Connection = ketnoi2;
                                                ketnoi2.Open();
                                                lenhsql2.ExecuteNonQuery();
                                                ketnoi2.Close();
                                                string sendMsg = "#ADDFR_OK#" + groupName + "#" + friendName + "#$#";
                                                ServerProcess.SendMessage(sendName,sendMsg);
                                            }
                                        }
                                        else
                                        {
                                            lenhsql2.CommandText = "SELECT ID_GROUP from [GROUP]";
                                            lenhsql2.CommandType = CommandType.Text;
                                            lenhsql2.Connection = ketnoi2;
                                            ketnoi2.Open();
                                            SqlDataReader reader = lenhsql2.ExecuteReader();
                                            gId = 0;
                                            while (reader.Read())
                                            {
                                                gId = (int)reader["ID_GROUP"];
                                            }
                                            gId++;
                                            ketnoi2.Close();
                                            lenhsql2.CommandText = "Select ID_USER from  ACCOUNT Where USER_NAME = '" + sendName + "'";
                                            lenhsql2.CommandType = CommandType.Text;
                                            lenhsql2.Connection = ketnoi2;
                                            ketnoi2.Open();
                                            SqlDataReader readIdUser = lenhsql2.ExecuteReader();
                                            int userId = 0;
                                            while (readIdUser.Read())
                                                userId = (int)readIdUser["ID_USER"];
                                            ketnoi2.Close();

                                            lenhsql2.CommandText = "Insert into [GROUP](ID_GROUP,GROUP_NAME,ID_USER) values('" + gId + "','" + groupName + "','" + userId + "')";
                                            lenhsql2.CommandType = CommandType.Text;
                                            lenhsql2.Connection = ketnoi2;
                                            ketnoi2.Open();
                                            lenhsql2.ExecuteNonQuery();
                                            ketnoi2.Close();
                                            lenhsql2.CommandText = "Insert into FRIEND(ID_FRIEND,ID_GROUP,FRIEND_NAME) values('" + fId + "','" + gId + "','" + friendName + "')";
                                            lenhsql2.CommandType = CommandType.Text;
                                            lenhsql2.Connection = ketnoi2;
                                            ketnoi2.Open();
                                            lenhsql2.ExecuteNonQuery();
                                            ketnoi2.Close();
                                            ServerProcess.SendMessage(sendName, "#ADDFR_OK#" + groupName + "#" + friendName + "#$#");
                                        }
                                    }
                                    else
                                    {
                                        ServerProcess.SendMessage(sendName, "#ADD_FAIL#Tài khoản không tồn tại");
                                    }
                                    ketnoi2.Close();
                                    break;
                             
                                // Xóa thành viên ra khỏi nhóm
                                // Kiểm tra xem tài khoản cần xóa có phải là bạn của người gửi hay không
                                // + Nếu không phải --> gửi thông báo tài khoản không hợp lệ
                                // + Nếu đúng: Xóa thành viên ra khỏi danh sách bạn bè của người gửi
                                // --> Gửi thông báo tới người gửi
                              
                                case "#DELETEFR#":
                                    // connect to database
                                    string path4 = MyConnectionString;
                                    SqlConnection ketnoi4 = new SqlConnection();
                                    ketnoi4.ConnectionString = path4;
                                    SqlCommand lenhsql4 = new SqlCommand();
                                    pos = msg.IndexOf("#");
                                    string friendDelete = msg.Substring(0, pos);
                                    msg = msg.Remove(0, pos + 1);
                                    pos = msg.IndexOf("#");
                                    string sendDelete = msg.Substring(0, pos);
                                    lenhsql4.CommandText = "Select ID_FRIEND from FRIEND where FRIEND_NAME = '" + friendDelete + "' AND ID_GROUP IN (Select ID_GROUP from [GROUP] G, ACCOUNT A where G.ID_USER = A.ID_USER AND A.USER_NAME = '" + sendDelete + "')";
                                    lenhsql4.CommandType = CommandType.Text;
                                    lenhsql4.Connection = ketnoi4;
                                    ketnoi4.Open();
                                    SqlDataReader readDeleteFriend = lenhsql4.ExecuteReader();
                                    int friendIdDel = 0;
                                    while (readDeleteFriend.Read())
                                        friendIdDel = (int)readDeleteFriend["ID_FRIEND"];
                                    ketnoi4.Close();
                                    if(friendIdDel != 0)
                                    {   
                                        lenhsql4.CommandText = "Delete from FRIEND where ID_FRIEND = '" +friendIdDel+"'";
                                        lenhsql4.CommandType = CommandType.Text;
                                        lenhsql4.Connection = ketnoi4;
                                        ketnoi4.Open();
                                        lenhsql4.ExecuteNonQuery();
                                        ketnoi4.Close();
                                        string delSuccess = "#DELETEOK#" + friendDelete;
                                        ServerProcess.SendMessage(sendDelete,delSuccess);
                                    }
                                    else
                                    { 
                                        string delFail = "#DEL_FAIL#" + "Tài khoản "+friendDelete+ " không hợp lệ";
                                        ServerProcess.SendMessage(sendDelete, delFail);
                                    }
                                    break;
                            }
                        }                      
                    }
                    // Xóa các tài nguyên liên quan đến luồng nhận dữ liệu
                    receiver.Dispose();
                }
                catch
                {
                    // Bước xử lí nào không thành công --> thông báo lỗi trên server
                    //MessageBox.Show("Lỗi kết nối");
                    // Gọi phương thức Exit() --> kết thúc tiến trình, thu hồi tài nguyên
                    Exit();
                }
            } 
            else
            {
                // Tin nhắn  đầu bị thất bại --> Không kết nối
                ServerProcess.ShowMessageLog("Không thể kết nối tới server");
                Exit();
            }
        }
      
        
        // Phương thức xử lí thông điệp  đầu tiên
        // Thông tin đăng kí
        // Thông tin đăng nhập
      
        public bool ProcessMsg(string msg)
        {
            // Lấy mã thông điệp
            string head = msg.Substring(0, 10);
            // Lấy nội dung thông điệp
            msg = msg.Remove(0, 10);
            int pos;
            // Mật khẩu người dùng
            string pass;
            // Tên người dùng
            string userName;
            bool _process = false;

            // Connect vao CSDL
            string path = MyConnectionString;
            SqlConnection ketnoi = new SqlConnection();
            ketnoi.ConnectionString = path;
            SqlCommand lenhsql = new SqlCommand();
            switch (head)
            {
               
                // Đăng kí tài khoản
                // Kiểm tra tài khoản đã tồn tại hay chưa
                // + Nếu đã tồn tại --> Gửi thông báo thất bại tới người gửi yêu cầu
                // + Nếu chưa --> Thêm vào csdl --> thông báo đăng kí thành công tới người gửi yêu cầu
               
                case "#REGISTER#":
                    // Lay userName
                    pos = msg.IndexOf("#");
                    userName = msg.Substring(0, pos);
                    msg = msg.Remove(0, pos + 1);
                    // Lay pass
                    pos = msg.IndexOf("#$#");
                    pass = msg.Substring(0, pos);
                    msg = msg.Remove(0, pos + 1);
                    lenhsql.CommandText = "Select COUNT(*) from ACCOUNT Where USER_NAME='" + userName + "' and PASSWORD='" + pass + "'";
                    lenhsql.CommandType = CommandType.Text;
                    lenhsql.Connection = ketnoi;
                    ketnoi.Open();
                     _process = true;
                    int dem = (int)lenhsql.ExecuteScalar();
                    ketnoi.Close();
                    if (dem > 0)
                    {
                        ServerProcess.AddUser(tcpClient, userName);
                        noticeStatus = "#REA_FAIL#register fail";
                        ServerProcess.SendMessage(userName, noticeStatus);
                        ServerProcess.RemoveUser(tcpClient);
                    }
                    else
                    {
                        lenhsql.CommandText = "SELECT ID_USER from ACCOUNT";
                        lenhsql.CommandType = CommandType.Text;
                        lenhsql.Connection = ketnoi;
                        ketnoi.Open();
                        SqlDataReader reader = lenhsql.ExecuteReader();
                        int id = 0;
                        while (reader.Read())
                        {
                            id = (int)reader["ID_USER"];
                        }
                        ketnoi.Close();
                        id++;
                        _process = true;
                        lenhsql.CommandText = "INSERT INTO ACCOUNT(ID_USER,STATUS,USER_NAME,PASSWORD) VALUES('"+id+"','0','" + userName + "','" + pass + "')";
                        lenhsql.CommandType = CommandType.Text;
                        lenhsql.Connection = ketnoi;
                        ketnoi.Open();
                        lenhsql.ExecuteNonQuery();
                        noticeStatus = "#REGISTER#success";
                        ServerProcess.ShowMessageLog(userName + " is connected to server");
                        ServerProcess.AddUser(tcpClient, userName);
                        ServerProcess.SendMessage(userName, noticeStatus);
                        ServerProcess.RemoveUser(tcpClient);
                    }
                    ketnoi.Close();
                    tcpClient.Close();
                    aThreadClient.Abort();
                    receiver.Close();
                    break;

                // Đăng nhập
                // Kiểm tra tài khoản đã tồn tại hay chưa
                // + Nếu tồn tại --> Lấy danh sách nhóm + thành viên --> gửi trở lại người yêu cầu
                //                   gửi tới các thành viên  khác thành viên này đã online
                // + Nếu tài khoản chưa tồn tại --> Thông báo đăng nhập thất bại tới người gửi yêu cầu
               
                case "#US_LOGIN#":
                    // Lay userName
                    pos = msg.IndexOf("#");
                    userName = msg.Substring(0, pos);
                    msg = msg.Remove(0, pos + 1);
                    // Lay pass
                    pos = msg.IndexOf("#$#");
                    pass = msg.Substring(0, pos);
                    msg = msg.Remove(0, pos + 1);
                    lenhsql.CommandText = "Select COUNT(*) from ACCOUNT Where USER_NAME='" + userName + "' and PASSWORD='" + pass + "'";
                    lenhsql.CommandType = CommandType.Text;
                    lenhsql.Connection = ketnoi;
                    ketnoi.Open();
                    int dem1 = (int)lenhsql.ExecuteScalar();
                    ketnoi.Close();

                    //check user already sign in by get Status with Username
                    // tôi định thêm đoạn này vào, nhưng check bị lỗi 
                    // Anhnn xem lại nhé.
                    lenhsql.CommandText = "Select STATUS from account where USER_NAME = '" + userName + "'";
                    lenhsql.CommandType = CommandType.Text;
                    lenhsql.Connection = ketnoi;
                    ketnoi.Open();
                    SqlDataReader readerLogin = lenhsql.ExecuteReader();
                    int iCheckLogin = 0;
                    while (readerLogin.Read())
                        iCheckLogin = (int)readerLogin.GetInt32(0);

                    
                    ketnoi.Close();
                    if (dem1 > 0) //&& iCheckLogin == 0)
                    {
                        lenhsql.CommandText = "SELECT  GROUP_NAME, ID_GROUP FROM  [GROUP] G, ACCOUNT A WHERE G.ID_USER = A.ID_USER  AND A.USER_NAME = '" + userName + "'";
                        lenhsql.CommandType = CommandType.Text;
                        lenhsql.Connection = ketnoi;
                        ketnoi.Open();
                        //get list group and friends on this list to send to loginner
                        SqlDataReader reader = lenhsql.ExecuteReader();
                        string group = null;
                        string id_group = null;
                      
                        while (reader.Read())
                        {
                            int idGroup = (int)reader["ID_GROUP"];
                            id_group += idGroup + "#";
                            group += (string)reader["GROUP_NAME"]+"#"; 
                        }
                        ketnoi.Close();
                        string listGroup = group;
                        if (group!= null)
                        {
                            
                            
                            while(group != "")
                            {
                                string aGroup = group.Substring(0, group.IndexOf("#"));
                                string idString = id_group.Substring(0, id_group.IndexOf("#"));
                                int id = (int)Int32.Parse(idString);
                                list += aGroup + "&&";
                                lenhsql.CommandText = "SELECT FRIEND_NAME FROM ACCOUNT A, FRIEND F WHERE A.ID_USER = F.ID_FRIEND AND A.STATUS = '1' AND F.ID_GROUP = '" + id + "'";
                                lenhsql.CommandType = CommandType.Text;
                                lenhsql.Connection = ketnoi;
                                ketnoi.Open();
                                SqlDataReader readFriend = lenhsql.ExecuteReader();
                                while (readFriend.Read())
                                {
                                    string friend_name = (string)readFriend["FRIEND_NAME"];
                                    if (friend_name != null)
                                    {
                                        list_friend += friend_name + "#";
                                        list += friend_name + "$";
                                    }
                                }
                                group = group.Remove(0, group.IndexOf("#") + 1);
                                id_group = id_group.Remove(0, id_group.IndexOf("#") + 1);
                                ketnoi.Close();
                                list += "#"; 
                            }           
                        }
                        ketnoi.Close();
                        lenhsql.CommandText = "Update ACCOUNT SET STATUS = '1' where USER_NAME = '" + userName + "'";
                        lenhsql.CommandType = CommandType.Text;
                        lenhsql.Connection = ketnoi;
                        ketnoi.Open();
                        lenhsql.ExecuteNonQuery();
                        ketnoi.Close();
                        ServerProcess.ShowMessageLog(userName + " is connected to server");
                        ServerProcess.AddUser(tcpClient, userName);
                        ServerProcess.SendMessage(userName, "#LSUCCESS#" + userName);

                        ServerProcess.UpdateMembersList(tcpClient, userName);
                        _process = true;
                    }
                    else
                    {
                        ServerProcess.AddUser(tcpClient, userName);
                        noticeStatus = "#LOG_FAIL#";
                        ServerProcess.SendMessage(userName, noticeStatus);
                        ServerProcess.RemoveUser(tcpClient);
                        _process = false;
                        tcpClient.Close();
                        aThreadClient.Abort();
                        receiver.Close();
                    }
                    break;

                // Nếu là trương hợp khác --> Mặc định giá trị trả về là false
                default:
                    _process = false;
                    break;
            }
            return _process;
        }
    }

}
